package com.zhongc.advance.common.code;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;


/**
 * 
 *                       
 * @Filename CodeImageGenerator.java
 *
 * @Description 
 *
 * @Version 1.0
 *
 * @Author yhl
 *
 * @Email 363881815@qq.com
 *       
 * @History
 *<li>Author: yhl<>
 *<li>Date: 2014-8-16<>
 *<li>Version: 1.0<>
 *<li>Content: create<>
 * 
 */
public class CodeImageGenerator {
	/**
	 * 字符库校验
	 */
	private final static Pattern pattern = Pattern.compile("[0-9a-zA-Z]{1,}");
	/**
	 * 随机数生成器
	 */
	private final static Random random = new Random();
	/**
	 * 默认字符库
	 */
	private char[] CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
	};
	/**
	 * 默认随机数生成极限值
	 */
	private int LIMIT = CHARS.length;
	/**
	 * 验证码长度，默认为4位
	 */
	private int length = 4;
	/**
	 * 图片宽度，默认为60
	 */
	private int width = 60;
	/**
	 * 图片高度，默认40
	 */
	private int height = 23;
	/**
	 * 干扰线条数
	 */
	private int interference = 3;
	/**
	 * 字体
	 */
	private String fontName = "Times New Roman";
	/**
	 * 字体大小
	 */
	private int fontSize = 18;
	/**
	 * 字体风格
	 */
	private int fontStyle = Font.PLAIN;
	/**
	 * 字体颜色
	 */
	private Color fontColor = Color.GRAY;
	/**
	 * 背景色
	 */
	private Color backgroundColor = Color.WHITE;
	/**
	 * 设置字符库
	 * @param alternative
	 */
	public void setAlternative(String alternative){
		if(alternative == null || !pattern.matcher(alternative).matches()){
			throw new RuntimeException("CodeImageGenerator->设置字符库失败:不合法的字符库");
		}
		CHARS = alternative.toCharArray();
		LIMIT = CHARS.length;
	}
	
	public void setFontColor(Color fontColor) {
		this.fontColor = fontColor;
	}

	public void setBackgroundColor(Color backgroundColor) {
		this.backgroundColor = backgroundColor;
	}

	public void setFontSize(int fontSize) {
		this.fontSize = fontSize;
	}

	public void setFontStyle(int fontStyle) {
		this.fontStyle = fontStyle;
	}

	public void setFontName(String fontName) {
		this.fontName = fontName;
	}

	public void setInterference(int interference) {
		this.interference = interference;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public void setLength(int length) {
		this.length = length;
	}

	/**
	 * 创建验证码
	 * @return
	 */
	public String createImageCode(){
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < length; i++) {
			builder.append(CHARS[random.nextInt(LIMIT)]);
		}
		return builder.toString();
	}
	/**
	 * 生成图片
	 * @param code
	 * @return
	 */
	public BufferedImage createIamge(String code){
		// 在内存中创建图象
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		// 获取图形上下文
		Graphics g = image.getGraphics();
		//设置背景色
		g.setColor(backgroundColor);
		//填充背景色
		g.fillRect(0, 0, width, height);
		// 设定字体
		g.setFont(getFont());
		//设置字体颜色
		g.setColor(fontColor);
		// 随机产生条干扰线，使图象中的认证码不易被其它程序探测到
		for (int i = 0; i < interference; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
		for (int i = 0; i < length; i++) {
			g.drawString(String.valueOf(code.charAt(i)), 13 * i + 6, 16);
		}
		g.dispose();
		return image;
	}
	
	private Font font = null;
	
	private Font getFont(){
		if(font == null){
			synchronized(CodeImageGenerator.class){
				font = new Font(fontName, fontStyle, fontSize);
			}
		}
		return font;
	}
	/**
	 * 生成图片
	 * @param code 验证码
	 * @param imageFormat 图片格式
	 * @param out 输出流
	 * @throws IOException 
	 */
	public void write(String code, String imageFormat, OutputStream out) throws IOException{
		ImageIO.write(createIamge(code), imageFormat, out);
	}
}
